package com.inwavetech.os.sync;

import android.accounts.Account;
import android.content.AbstractThreadedSyncAdapter;
import android.content.ContentProviderClient;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.SyncResult;
import android.os.Bundle;
import android.util.Log;

import com.inwavetech.os.R;
import com.inwavetech.os.entity.enummap.OsClosingStatusMap;
import com.inwavetech.os.entity.enummap.OsServiceOrderTypeMap;
import com.inwavetech.os.entity.enummap.OsStatusMap;
import com.inwavetech.os.entity.enummap.ProductDiagnosysMap;
import com.inwavetech.os.sync.jsonparser.OsJsonParser;
import com.inwavetech.os.sync.jsonparser.ProductJsonParser;
import com.inwavetech.os.util.DaoHelper;
import com.inwavetech.os.util.SessionManager;
import com.inwavetech.os.util.SyncDateFormat;
import com.inwavetech.os.util.WsseRequestConfigurator;
import com.inwavetech.os.util.request.Get;

import java.sql.SQLException;

/**
 * Created by jgskin on 2/19/14.
 */
public class SyncAdapter extends AbstractThreadedSyncAdapter {

    public static final String SYNC_STATUS_ACTION = "com.inwavetech.os.sync.SyncAdapter.SYNC_STATUS";
    public static final String SYNC_STATUS_KEY = "status";
    public static final int SYNC_STATUS_PROCCESS = 1;
    public static final int SYNC_STATUS_FAIL = 2;
    public static final int SYNC_STATUS_SUCCESS = 3;

    // Global variables
    // Define a variable to contain a content resolver instance
    ContentResolver mContentResolver;

    /**
     * Set up the sync adapter
     */
    public SyncAdapter(Context context, boolean autoInitialize) {
        super(context, autoInitialize);
        /*
         * If your app uses a content resolver, get an instance of it
         * from the incoming Context
         */
        mContentResolver = context.getContentResolver();
    }

    @Override
    public void onPerformSync(
            Account account,
            Bundle extras,
            String authority,
            ContentProviderClient provider,
            SyncResult syncResult) {
        broadcastStatus(SYNC_STATUS_PROCCESS);

        DaoHelper daoHelper = new DaoHelper(getContext());

        // finished os remover should not be here
        FinishedOsRemover finishedOsRemover = new FinishedOsRemover(daoHelper);
        try {
            finishedOsRemover.execute();
        } catch (SQLException e) {
            logException(FinishedOsRemover.class.getName(), e);
        }
        // finished os remover should not be here

        int status = SYNC_STATUS_SUCCESS;

        OsSyncer osSyncer;
        try {
            osSyncer = new OsSyncer(getContext());
            osSyncer.syncFinishedOs();
        } catch (OsSyncer.OsSyncerException e) {
            logException("unauthenticated user", e);
            // bad status broadcast
            status = SYNC_STATUS_FAIL;
        } catch (SQLException e) {
            logException("database error", e);
            // bad status broadcast
            status = SYNC_STATUS_FAIL;
        } catch (OsSender.OsSenderException e) {
            logException("bad server response", e);
            // bad status broadcast
            status = SYNC_STATUS_FAIL;
        }

        // os updater
        SessionManager sessionManager = new SessionManager(getContext(), daoHelper);
        SyncDateFormat syncDateFormat = new SyncDateFormat();
        OsUpdater updater = new OsUpdater(
                daoHelper,
                sessionManager,
                new Get(new WsseRequestConfigurator(sessionManager)),
                syncDateFormat,
                new OsJsonParser(
                        new OsStatusMap(),
                        new OsClosingStatusMap(),
                        new OsServiceOrderTypeMap(),
                        syncDateFormat
                ),
                new ProductJsonParser(new ProductDiagnosysMap(), syncDateFormat),
                getContext().getString(R.string.api_get_oses)
        );

        try {
            updater.execute();
        } catch (Exception e) {
            logException("", e);
            // bad status broadcast
            status = SYNC_STATUS_FAIL;
        }

        broadcastStatus(status);
    }

    private void broadcastStatus(int status) {
        Intent i = new Intent(SYNC_STATUS_ACTION);
        i.putExtra(SYNC_STATUS_KEY, status);

        getContext().sendBroadcast(i);
    }

    private void logException(String message, Exception e) {
        Log.e(getClass().getName(), String.format("%s - %s - %s", message, e.getClass().getName(), e.getMessage()));
    }

}
